package cn.eeepay.framework.service.unTransactionalImpl.wetchatPublic.impl;

import cn.eeepay.framework.dao.MerchantInfoDao;
import cn.eeepay.framework.dao.SysDictDao;
import cn.eeepay.framework.dao.wetchatPublic.PublicAccountMsgBatchDao;
import cn.eeepay.framework.dao.wetchatPublic.PublicAccountMsgTempDao;
import cn.eeepay.framework.db.pagination.Page;
import cn.eeepay.framework.model.UserLoginInfo;
import cn.eeepay.framework.model.wetchatPublic.PublicAccountMsgBatchEntity;
import cn.eeepay.framework.model.wetchatPublic.PublicAccountMsgTempEntity;
import cn.eeepay.framework.model.wetchatPublic.PublicAccountUserTempEntity;
import cn.eeepay.framework.service.BossSysConfigService;
import cn.eeepay.framework.service.unTransactionalImpl.wetchatPublic.PublicAccountMsgBatchService;
import cn.eeepay.framework.util.*;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.usermodel.WorkbookFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.text.SimpleDateFormat;
import java.util.*;

@Service("publicAccountMsgBatchService")
public class PublicAccountMsgBatchServiceImpl implements PublicAccountMsgBatchService {

    private Logger log = LoggerFactory.getLogger(PublicAccountMsgBatchServiceImpl.class);

    @Resource
    private PublicAccountMsgBatchDao publicAccountMsgBatchDao;

    @Resource
    private PublicAccountMsgTempDao publicAccountMsgTempDao;

    @Resource
    private MerchantInfoDao merchantInfoDao;

    @Resource
    private SysDictDao sysDictDao;

    @Resource
    private BossSysConfigService bossSysConfigService;

    @Override
    public PublicAccountMsgBatchEntity getById(Long id) {
        return publicAccountMsgBatchDao.getById(id);
    }

    @Override
    public List<PublicAccountMsgBatchEntity> queryPage(
            Page<PublicAccountMsgBatchEntity> page, PublicAccountMsgBatchEntity info) {
        List<PublicAccountMsgBatchEntity> publicAccountMsgBatchEntities =
                publicAccountMsgBatchDao.queryPage(page, info);
        if (page.getResult() != null && page.getResult().size() > 0) {
            for (PublicAccountMsgBatchEntity entity : page.getResult()) {
                entity.setTimeBlock(StringUtil.filterNull(entity.getEffectiveStartTime()) + "--" + StringUtil.filterNull(entity.getEffectiveEndTime()));
            }
        }
        return publicAccountMsgBatchEntities;
    }

    @Override
    public ResultModel importBatch(MultipartFile file, PublicAccountMsgBatchEntity info) throws Exception {

        // 批次号
        String pushBatchNo = StringUtil.getStringRandom(16);
        PublicAccountMsgTempEntity tempInfo = publicAccountMsgTempDao.getById(info.getTempId());

        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date now = new Date();
        JSONObject object = new JSONObject();
        object.put("first", info.getMsgContent());
        object.put("remark", info.getMsgRemark());
        object.put("redirect_url", info.getMsgUrl());
        objectPutKey(tempInfo.getCode(),object);
        String userTypeName = sysDictDao.getSysNameByKV("MSG_TO_USER_TYPE", info.getUserType());

        info.setMsgData(object.toJSONString());

        Workbook wb = WorkbookFactory.create(file.getInputStream());
        int success = 0;
        int fail = 0;
        Sheet sheet = wb.getSheetAt(0); // 读取第一个sheet
        int row_num = sheet.getLastRowNum();
        if (row_num > 50000) {
            return ResultModel.error("导入文件支持最高5万条");
        }

        List<PublicAccountUserTempEntity> preSaveList = new ArrayList<>();

        for (int i = 1; i <= row_num; i++) {
            Row row = sheet.getRow(i);
            String merchantNo = CellUtil.getCellValue(row.getCell(1)); // 商户号
            String pubName = CellUtil.getCellValue(row.getCell(2)); // 公众号

            // 商户不存在
            if (merchantNoNotExists(merchantNo)) {
                fail++;
                continue;
            }
            // 微信表不存在
            String openId = getOpenIdByMerchantNo(merchantNo, tempInfo.getPubAcc());
            if (StringUtil.isBlank(getOpenIdByMerchantNo(merchantNo, tempInfo.getPubAcc()))) {
                fail++;
                continue;
            }
            // 每1000条批量插入一次
            if (preSaveList.size() > 1000) {
                log.info("批量插入:" + i);
                publicAccountMsgBatchDao.saveTempUser(preSaveList);
                preSaveList.clear();
            } else {
                PublicAccountUserTempEntity tempUser = new PublicAccountUserTempEntity();
                tempUser.setPushBatchNo(pushBatchNo);
                tempUser.setOpenid(openId);
                tempUser.setPublicAcc(tempInfo.getPubAcc());
                tempUser.setCreateTime(now);
                preSaveList.add(tempUser);
            }
            success++;
        }

        // 不满1000条记录
        if (preSaveList.size() > 0) {
            log.info("剩余批量插入:" + preSaveList.size());
            // 保存临时表信息
            publicAccountMsgBatchDao.saveTempUser(preSaveList);
            preSaveList.clear();
        }

        info.setMsgData(object.toJSONString());
        info.setUserTypeName(userTypeName);
        info.setUserCount(success);
        //最初逻辑
        info.setBindStatus(tempInfo.getCode().equals("STATUS_RESULT_WX")?"绑定成功":tempInfo.getCode().equals("STATUS_REMIND_WX")?"未绑定":"");
        info.setTitle(tempInfo.getTitle());
        info.setPushStatus("SENDING");
        final UserLoginInfo principal =
                (UserLoginInfo) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        info.setOperator(principal.getUsername());
        info.setPushTime(now);
        info.setCreateTime(now);
        info.setPushTimeStr(sdf.format(now));
        info.setPushBatchNo(pushBatchNo);
        info.setMsgTempId(tempInfo.getMsgTempId());
        publicAccountMsgBatchDao.save(info);

        return ResultModel.ok().put("info", info)
                .put("pushBatchNo", pushBatchNo)
                .put("importResult", "导入商户：" + success + " 成功，" + fail + " 失败")
                .put("toNext", fail == 0);
    }

    private boolean merchantNoNotExists(String merchantNo) {
        return merchantInfoDao.selectByMerNo(merchantNo) == null;
    }

    private String getOpenIdByMerchantNo(String merchantNo, String pubAcc) {
        return publicAccountMsgBatchDao.getOpenIdByMerchantNo(merchantNo, pubAcc);
    }

    private void objectPutKey(String code,JSONObject object){
        String jsonStr=bossSysConfigService.selectValueByKey(code);
        JSONObject jsonKey=JSON.parseObject(jsonStr);
        if(jsonKey!=null){
            for (Map.Entry<String, Object> entry : jsonKey.entrySet()) {
                if(entry.getValue().equals("DATE")){
                    entry.setValue(DateUtil.getLongCurrentDate());
                    break;
                }
            }
            object.putAll(jsonKey);
        }
        log.info("微信推送文本格式：{},code:{}",object.toJSONString(),code);
    }

    @Override
    public ResultModel save(PublicAccountMsgBatchEntity info) {
        // 批次号
        String pushBatchNo = StringUtil.getStringRandom(16);
        PublicAccountMsgTempEntity tempInfo = publicAccountMsgTempDao.getById(info.getTempId());
        info.setPushBatchNo(pushBatchNo);
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date now = new Date();
        JSONObject object = new JSONObject();
        object.put("first", info.getMsgContent());
        object.put("remark", info.getMsgRemark());
        object.put("redirect_url", info.getMsgUrl());
        objectPutKey(tempInfo.getCode(),object);
        info.setMsgData(object.toJSONString());
        info.setPushStatus("SENDING");
        final UserLoginInfo principal =
                (UserLoginInfo) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        info.setOperator(principal.getUsername());
        info.setPushTime(now);
        info.setCreateTime(now);
        info.setTitle(publicAccountMsgTempDao.getById(info.getTempId()).getTitle());
        //最初逻辑
        info.setBindStatus(tempInfo.getCode().equals("STATUS_RESULT_WX")?"绑定成功":tempInfo.getCode().equals("STATUS_REMIND_WX")?"未绑定":"");
        info.setPushTimeStr(sdf.format(now));
        String userTypeName = sysDictDao.getSysNameByKV("MSG_TO_USER_TYPE", info.getUserType());
        info.setUserTypeName(userTypeName);
        if (info.getUserType().equals("SUBSCRIBE")) {
            info.setUserCount(publicAccountMsgBatchDao.getUserCountByPubAcc(tempInfo.getPubAcc()));
        }
        info.setMsgTempId(tempInfo.getMsgTempId());
        publicAccountMsgBatchDao.save(info);
        return ResultModel.ok().put("info", info).put("pushBatchNo", pushBatchNo).put("toNext", true);
    }

    @Transactional
    @Override
    public void removeByPushBatchNo(String pushBatchNo) {
        PublicAccountMsgBatchEntity info = publicAccountMsgBatchDao.getInfoByBatchNo(pushBatchNo);
        if(info!=null){
            publicAccountMsgBatchDao.removeByPushBatchNo(pushBatchNo);
            publicAccountMsgBatchDao.removePushDetail(pushBatchNo);
            if("CUSTOM".equals(info.getUserType())){
                publicAccountMsgBatchDao.removeTempUser(pushBatchNo);
            }
        }
    }


    @Override
    public ResultModel stop(Long id) {
        int result = publicAccountMsgBatchDao.updatePushStatus(id, "STOP");
        if (result == 1) {
            return ResultModel.ok("终止成功");
        }
        return ResultModel.error("终止失败");
    }

    @Override
    public ResultModel start(Long id) {
        try {
            PublicAccountMsgBatchEntity info = publicAccountMsgBatchDao.getById(id);

            if (info.getEffectiveStartTime() == null || info.getEffectiveEndTime() == null) {
                return ResultModel.error("发送时间段为空！");
            }
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy-MM-dd");
            String nowStr = sdf1.format(new Date());
            Date begin = sdf.parse(nowStr + " " + info.getEffectiveStartTime());
            Date end = sdf.parse(nowStr + " " + info.getEffectiveEndTime());
            Date now = new Date();

            if (now.getTime() <= begin.getTime() || now.getTime() >= end.getTime()) {
                return ResultModel.error("当前时间不在有效发送时间段内");
            }
            int result = publicAccountMsgBatchDao.updatePushStatus(id, "SENDING");
            if (result == 1) {
                //调core发送
                send(info.getPushBatchNo());
            }
        } catch (Exception e) {
            log.error("继续发送失败", e);
            return ResultModel.error("继续发送失败");
        }
        return ResultModel.ok("继续发送成功");
    }

    @Override
    public ResultModel suspend(Long id) {
        int result = publicAccountMsgBatchDao.updatePushStatus(id, "SUSPEND");
        if (result == 1) {
            return ResultModel.ok("暂停成功");
        }
        return ResultModel.error("暂停失败");
    }

    @Override
    public int updateTimeBlock(PublicAccountMsgBatchEntity publicAccountMsgBatch) {
        return publicAccountMsgBatchDao.updateTimeBlock(publicAccountMsgBatch);
    }

    @Override
    public ResultModel send(String pushBatchNo) {
        String checkMerchantNo = pushBatchNo;
        String Token = "a185faf4c55807bca4bcfdaae06b58fa";
        String USER_INFO_ID = "4IE5DhZE4IJ2gdv9YmDr6jfaaIBBlyafFNPz2wYXtqN";
        String PATH = "/weChat/commonWxPush";
        String authCode = Md5.md5Str(USER_INFO_ID + checkMerchantNo + Token).toUpperCase();
        String url = sysDictDao.getByKey("CORE_URL").getSysValue() + PATH;

        Map<String, String> requestMap = new HashMap<>();
        requestMap.put("token", Token);
        requestMap.put("authCode", authCode);
        requestMap.put("merchantNo", checkMerchantNo);
        requestMap.put("batchNo", pushBatchNo);
        requestMap.put("teamId", "200010");

        log.info("微信推送 url:{},\n  参数：{}\n", url, JSONObject.toJSONString(requestMap));
        String result = HttpUtils.sendPostRequest(url, requestMap);
        log.info("微信推送结果 ：{}", result);

        return ResultModel.ok("发送成功");
    }
}
